<!-- 分段线，在一条线上划分多个区间 -->
<script setup lang="ts">
import { computed } from "vue";

export type Mark = {
  /**
   * 刻度值
   */
  value: number;
  /**
   * 显示在刻度上的文字
   */
  text?: string;
  /**
   * 是否显示小圆点
   */
  showDot?: boolean;
  /**
   * 小圆点颜色
   */
  dotColor?: string;
  /**
   * 从当前刻度到下一个刻度之间的段落颜色
   */
  scopeColor?: string;
};
interface Props {
  marks: Mark[];
}
const props = defineProps<Props>();
const defaultBgColor = "#ECF1F4";
// 用于渲染的刻度列表
const markList = computed(() => {
  const orgMarks = props.marks || [];
  if (orgMarks.length < 2) {
    return [];
  }
  const sortedMarks = orgMarks.sort((a, b) => a.value - b.value);
  const minMark = sortedMarks[0].value ?? 0;
  const maxMark = sortedMarks[props.marks.length - 1].value ?? 100;
  const total = maxMark - minMark;
  const list = [];
  let leftSum = 0;
  for (let i = 0; i < sortedMarks.length; i++) {
    const isLast = i === sortedMarks.length - 1;
    const item = sortedMarks[i];
    const itemVal = item.value;
    const nextItem = isLast ? null : sortedMarks[i + 1];
    const nextItemVal = nextItem?.value ?? maxMark;
    const widthVal = nextItemVal - itemVal;
    const widthRatio = isLast ? 0 : toRatio(widthVal, total);
    // const styleLeft = `${toRatio(itemVal - minMark, total) * 100}%`;
    const styleLeft = `${leftSum}%`;
    list.push({
      ...item,
      widthRatio,
      style: {
        left: styleLeft,
        width: `${widthRatio * 100}%`,
        backgroundColor: item.scopeColor || defaultBgColor
      },
      dotStyle: {
        borderColor: item.dotColor
      },
      annotationStyle: {
        left: styleLeft
      }
    });
    leftSum += widthRatio * 100;
  }
  return list;
});
const hasAnnotation = computed(() => {
  return markList.value.some(p => p.text);
});
// 保留4位精度小数
const toRatio = (val: number, max: number) => {
  return Math.floor((val / max) * 10000) / 10000;
};
defineExpose({
  getMarkList() {
    return markList.value;
  }
});
</script>

<template>
  <div class="v-segmented-line">
    <div class="v-segmented-line__ruler">
      <div
        v-for="mark in markList"
        :key="mark.value"
        class="v-segmented-line__mark"
        :style="mark.style"
      >
        <div
          v-if="mark.showDot"
          class="v-segmented-line__mark-dot"
          :style="mark.dotStyle"
        />
      </div>
    </div>
    <div v-if="hasAnnotation" class="v-segmented-line__annotation">
      <span
        v-for="mark in markList"
        :key="mark.value"
        class="v-segmented-line__annotation-item"
        :style="mark.annotationStyle"
        >{{ mark.text }}</span
      >
    </div>
  </div>
</template>

<style lang="scss" scoped>
$bg-color: #ecf1f4;
$line-radius: 2px;

.v-segmented-line {
  --bar-height: var(--v-segmented-line-bar-height, 2px);

  &__ruler {
    position: relative;
    width: 100%;
    height: var(--bar-height);
    background-color: $bg-color;
    border-radius: $line-radius;
  }

  &__mark {
    position: absolute;
    top: 0;
    height: var(--bar-height);
    border-radius: $line-radius;

    &-dot {
      box-sizing: border-box;
      position: absolute;
      left: -3px;
      top: -3px;
      width: 7px;
      height: 7px;
      border: 2px solid var(--color-primary);
      border-radius: 50%;
      background-color: transparent;
    }
  }

  &__annotation {
    position: relative;
    margin-top: 4px;
    height: 20px;
  }

  &__annotation-item {
    position: absolute;
    top: 0;
    font-size: 12px;
    color: #666666;
    transform: translateX(-50%);
  }
}
</style>
